[网络流24题]家园

2020-01-31
网络流24题

题意

有$m$艘飞船在地球、月球和$n$个空间站间周期性地穿梭,第i艘船的容量为$h_i$

地球上有$k$个人,求最少的时间,把他们全部转移到月球上

题解

关于每一个时间点建一层图,飞船穿梭以其容量为流量连边即可

每次加入新的边可以在原来的残余网络上继续跑Dinic

调试记录

忘记判断方案存在性

当前弧优化,不加T一个点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
const int maxn = 5e4 + 5;
const int S = 50000;
const int T = 50001;
const int INF = 0x3f3f3f3f;
#define D (tim * (n + 1))
#define P ((tim - 1) * (n + 1))
#define Pre r[i][(tim - 1) % r[i].size()]
#define Now r[i][tim % r[i].size()]
using namespace std;
struct E{
int to, nxt, f;
}e[maxn << 1];
int head[maxn], tot = 1;
void addedge(int u, int v, int f){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].f = f;
head[u] = tot;
}
void ins(int u, int v, int f){
addedge(u, v, f); addedge(v, u, 0);
}
int n, m, k, h[25];
vector <int> r[25];
int dep[maxn], now[maxn];
bool bfs(){
queue <int> q; while (!q.empty()) q.pop(); q.push(S);
memset(dep, 0, sizeof dep); dep[S] = 1;
memcpy(now, head, sizeof head);
while (!q.empty()){
int cur = q.front(); q.pop();
for (int i = head[cur]; i; i = e[i].nxt)
if (e[i].f > 0 && dep[e[i].to] == 0){
dep[e[i].to] = dep[cur] + 1;
q.push(e[i].to);
}
}
return dep[T] != 0;
}
int dfs(int cur, int Max){
if (cur == T) return Max;
int flow = 0;
for (int i = now[cur]; i; i = e[i].nxt){
int v = e[i].to; now[cur] = i;
if (flow == Max) return flow;
if (dep[v] == dep[cur] + 1 && e[i].f > 0){
int tmp = dfs(v, min(Max - flow, e[i].f));
e[i].f -= tmp;
e[i ^ 1].f += tmp;
flow += tmp;
}
}
return flow;
}
int maxflow = 0;
void Dinic(){
while (bfs())
maxflow += dfs(S, INF);
}
int f[maxn];
int getf(int x){return f[x] == x ? x : f[x] = getf(f[x]);}
int main(){
// freopen("2.in", "r", stdin);
scanf("%d%d%d", &n, &m, &k);
for (int i = 0; i <= n; i++) f[i] = i; f[T] = T;
for (int tmp, i = 1; i <= m; i++){
scanf("%d%d", h + i, &tmp);
for (int x, j = 0; j < tmp; j++){
scanf("%d", &x);
if (x == -1) x = T;
for (int k = 0; k < r[i].size(); k++)
if (getf(r[i][k]) != getf(x)) f[getf(r[i][k])] = getf(x);
r[i].push_back(x);
}
}
if (getf(0) != getf(T)){
puts("0"); return 0;
}
// for (int i = 1; i <= m; i++){
// for (int j = 0; j < r[i].size(); j++) printf("%d ", r[i][j]);
// puts("");
// }
ins(S, 0, k);
int tim = 0;
while (maxflow < k){
++tim;
for (int i = 1; i <= m; i++)
if (Pre != T){
if (Now == T) ins(Pre + P, T, h[i]);
else ins(Pre + P, Now + D, h[i]);
}
for (int i = 0; i <= n; i++)
ins(i + P, i + D, INF);
Dinic();
}
printf("%d\n", tim);
return 0;
}